package edu.kit.aifb.ldstream.cli;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.openrdf.model.vocabulary.RDFS;
import org.openrdf.repository.RepositoryException;
import org.openrdf.repository.sail.SailRepository;
import org.openrdf.rio.RDFFormat;

import org.openrdf.sail.inferencer.fc.ForwardChainingRDFSInferencer;
import org.openrdf.sail.memory.MemoryStore;
import org.openrdf.sail.nativerdf.NativeStore;

import joptsimple.OptionParser;
import joptsimple.OptionSet;

import edu.kit.aifb.ldstream.env.Environment;
import edu.kit.aifb.ldstream.learner.Learner;
import edu.kit.aifb.ldstream.repository.RepositoryBuilder;



/**
 * Class for starting  RepositoryBuilder & Learner.
 * 
 * Starting the RepositoryBuilder & Learner after initializing global variables needed for the computation.
 * 
 * @author Holger
 *
 */
public class CLI {

	private static final String V = "v";
	private static final String L = "l";
	private static final String I = "i";
	private static final String C = "c";

	/**
	 * Used to start RepositoryBuilder & Learner.
	 * 
	 * @param args Starter options, the following are available
	 *        <ul>
	 *        	<li> -c Path of the configuration file </li>
	 *        	<li> -v Verbose mode </li>
	 *        	<li> -l Lookups </li>
	 *        	<li> -i Inferencing </i>
	 *        </ul>
	 *        
	 */
	public static void main(String[] args) {

		if(initializeRepository(Environment.DEFAULT_REPO_LOCATION)){
			ExecutorService threadPool = Executors.newFixedThreadPool(Environment.NUM_THREADS);
			RepositoryBuilder rbuilder = new RepositoryBuilder(threadPool);			
			
			// Reading args and initializing repository
			if(init(args, rbuilder)){
				Environment.LOOKUPS = false;
				

				rbuilder.start();
				try {
					rbuilder.join();
				} catch (InterruptedException e1) {}

				Learner learner = new Learner(threadPool);
				learner.learn();

				shutdown();
			}
			threadPool.shutdown();
		}
	}

	private static void shutdown(){
		try {
			Environment.REPO.shutDown();
		} catch (RepositoryException e) {
			e.printStackTrace();
		}
	}

	private static boolean init(String[] args, RepositoryBuilder repoBuilder){
		boolean success = true;
		OptionParser op = new OptionParser();
		op.accepts(C, "Path of the config file").withRequiredArg().ofType(String.class);
		op.accepts(L, "Enables lookups");
		op.accepts(V, "Verbose mode");
		op.accepts(I, "Enables inferencing");
		OptionSet os = op.parse(args);

		if(os.has(V)){
			Environment.VERBOSE = true;
		}
		if(os.has(L)){
			Environment.LOOKUPS = true;
		}
		if(os.has(I)){
			Environment.INFERENCING = true;
		}
		if(os.has(C)){
			BufferedReader br= null;
			try {
				br = new BufferedReader(new FileReader(new File((String) os.valueOf(C))));
				String stream = br.readLine();
				String[] arg;
				while(stream != null){
					arg = stream.split(" ");
					if(arg.length == 4 && arg[0].equalsIgnoreCase("s")){
						repoBuilder.addStream(arg[1], arg[2], Integer.parseInt(arg[3]));
					} else if(arg.length == 3 && arg[0].equalsIgnoreCase("f")){
						repoBuilder.addFile(arg[1], arg[2], null);
					}else{
						System.err.println("Wrong input format.");
					}
					stream = br.readLine();
				}
			} catch (FileNotFoundException e) {
				success = false;
				e.printStackTrace();
			} catch (IOException e) {
				success = false;
				e.printStackTrace();
			}finally{
				if(br != null){
					try {
						br.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
		return success;
	}

	private static boolean initializeRepository(String repoPath){
		boolean success = true;
		File repoFile = new File(repoPath);
		if(!repoFile.exists()){
			repoFile.mkdir();
			try {
				repoFile.createNewFile();
			} catch (IOException e) {
				success = false;
				System.err.println("Could not create repository location");
			}
		}
		MemoryStore store = new MemoryStore(repoFile);
		store.setSyncDelay(150);
		Environment.REPO = new SailRepository(new ForwardChainingRDFSInferencer(store));
		//	Environment.REPO = new SailRepository(new ForwardChainingRDFSInferencer(new NativeStore(repoFile /* "psoc,opsc,spoc" */)));
		try {
			Environment.REPO.initialize();
		} catch (RepositoryException e) {
			success = false;
			System.err.println("Could not initialize repository");
		}
		if(Environment.VERBOSE){
			System.out.println("Repository initialized at: " + repoFile.getAbsolutePath());
		}
		return success;
	}

}
